import React, { useState, useEffect, useRef, useMemo } from 'react';
import { printControlMap } from './data';
import { ControlType } from './../config';
import { tableIdToName, getActionFiled, includesControl } from './../view/util';
import evalScript from '../eval';
import { ViewProps, ControlProps } from './interface';
import { ActionFieldType, ControlRefProps } from './../interface';
import style from './print.module.scss';

import PrintTable from './components/table/PrintTable';
import { AUDIT_HISTORY_STATUS } from './../../../configs';

type DataType = Record<string, any>;
const T = window.$app.t;
const tableProps = {
  "showItemNo": false,
  "columns": [
    {
      title: T('createdAt'),
      "dataIndex": "createdAt",
      "width": 200,
      "key": "c9113c03-5110-4405-95ba-89ac470a46fa",
      "type": "datePicker",
      "options": {
        "format": "YYYY/MM/DD HH:mm:ss"
      },
      "originalIndex": 2
    },
    {
      title: T('assignUserName'),
      "width": 136,
      "dataIndex": "assignUserName",
      "key": "04ae37ff-019a-473a-8c60-875fc050ec98",
      "options": {},
      "type": "input"
    },
    {
      title: T('taskName'),
      "dataIndex": "taskName",
      "width": 376,
      "key": "ecc0bc48-f5de-463c-9735-5c6b14a3a8ee",
      "options": {},
      "type": "input"
    },
    {
      title: T('action'),
      dataIndex: 'actionName',
      width: 136,
      render: (text: string, record: any) => {
        if (record.actionName) return record.actionName;
        return AUDIT_HISTORY_STATUS[record.action] || '';
      }
    },
    {
      dataIndex: 'transferToUserName',
      title: window.$app.t('forwardTo'),
      tooltip: true,
      ellipsis: true,
      render: (_: unknown, record: any) => `${record.transferToEmployeeCode || ''}-${record.transferToUserName || ''}`,
      width: 120
    },
    {
      "title": T('auditComment'),
      "dataIndex": "comment",
      "width": 136,
      "key": "76cc9611-5875-48c6-aede-54ca1ab76353",
      "type": "input",
      "options": {}
    }
  ]
};

export default ({ data, structure, formInfo, hideFields }: ViewProps) => {
  const controlRefs = useRef<Record<string, ControlRefProps>>({}); // 控件ref集合
  const [controlExtraOptions, setControlExtraOptions] = useState<ActionFieldType>({}); // 脚本额外控制控件
  const [transferData, setTransferData] = useState<DataType>({});
  const [historyLine, setHistoryLine] = useState<any[]>([]);
  const scriptsLoadTimer = useRef<any>(null);
  const [isRender, setIsRender] = useState(false);

  useEffect(() => {
    setTransferData((prev: DataType) => ({ ...prev, ...data }));
  }, [data]);

  useEffect(() => {
    if (!structure.list) return;

    setControlExtraOptions(prev => {
      const fieldsMap = {};

      hideFields?.forEach(item => {
        const k = tableIdToName(item, structure.list)!;

        if (!fieldsMap[k]) fieldsMap[k] = {};
        fieldsMap[k].hide = true;
      });

      return { ...fieldsMap, ...prev };
    });
  }, [hideFields, structure.list]);

  const scriptsLoad = useMemo(() => {
    const scriptsLoad: string[] = [];

    structure.list?.forEach(item => {
      if (item.type === ControlType.SCRIPT_LOAD && item.options?.scriptText) {
        scriptsLoad.push(item.options.scriptText);
      }
    });

    return scriptsLoad;
  }, [structure.list]);

  const scriptsBefore = useMemo(() => {
    const scriptsBefore: string[] = [];

    structure.list?.forEach(item => {
      if (item.type === ControlType.SCRIPT_BEFORE && item.options?.scriptText) {
        scriptsBefore.push(item.options.scriptText);
      }
    });

    return scriptsBefore;
  }, [structure.list]);

  useEffect(() => {
    if (scriptsLoadTimer.current) {
      clearTimeout(scriptsLoadTimer.current);
      scriptsLoadTimer.current = null;
    }

    scriptsLoadTimer.current = setTimeout(() => {
      // before脚本存在，需执行完再执行load脚本

      if (scriptsBefore.length) {
        evalScript({
          scriptText: scriptsBefore[0],
          extra: {
            _ENV_: structure.enviromentConfig || {},
            _OBJ_: data || {},
            _OBJ1_: data,
            _QUERY_: {},
            _PRINT_: false,
          },
          next: ((result: any, actionFiled: ActionFieldType) => {
            if (actionFiled) {
              setControlExtraOptions(prev => {
                return { ...prev, ...actionFiled };
              });
            }

            data = { ...data, ...result };
            setTransferData((prev: any) => ({ ...prev, ...data }));
            _loadFn(result);
          })
        });
      } else {
        _loadFn();
      }


      function _loadFn(beforeObj?: object) {
        if (beforeObj) Object.assign(data!, beforeObj);
        setIsRender(true);
        if (scriptsLoad.length) {
          let loadRtnData = data;
          evalScript({
            scriptText: scriptsLoad[0],
            extra: {
              _OBJ_: data || {},
              _OBJ1_: loadRtnData,
              _ENV_: structure.enviromentConfig || {},
              _QUERY_: {},
              _PRINT_: true
            },
            next: ((result: DataType, actionFiled: ActionFieldType) => {
              if (actionFiled) {
                setControlExtraOptions(prev => {
                  return { ...prev, ...actionFiled };
                });
              }

              loadRtnData = { ...loadRtnData, ...result };
              setTransferData((prev: any) => ({ ...prev, ...loadRtnData }));
            })
          });
        }
      }

    }, 200);
  }, [scriptsLoad, scriptsBefore, data, structure.enviromentConfig]);

  function renderControl(item: ControlProps) {

    if (item.options?.formItemProps?.print === false || item.options?.print === false) return null;
    if (item.options?.formItemProps?.hideInput) return null;

    const Control: any = printControlMap[item.type];
    if (!Control) return null;

    const options: any = { ...item.options, key: item.id, enviromentConfig: structure.enviromentConfig || {}, };
    const currActionFiled = getActionFiled(controlExtraOptions, item);

    // 字段隐藏 跳过 hideFields
    if (typeof currActionFiled.hide === 'boolean') {
      if (currActionFiled.hide) {
        if (currActionFiled.hideExcludes) {
          if (!includesControl(currActionFiled.hideExcludes, item)) {
            return null;
          }
        } else {
          return null;
        }
      } else {
        if (currActionFiled.hideExcludes && includesControl(currActionFiled.hideExcludes, item)) {
          return null;
        }
      }
    }

    // table
    if (item.type === 'table') {
      options.tableProps!.columns = options.tableProps!.columns.filter((column: any) => {
        const id = options.name + '#' + column.dataIndex;
        const currActionFiled = controlExtraOptions[id] || {};

        return !(typeof currActionFiled.hide === 'boolean' ? currActionFiled.hide : false);
      });
    }

    if (item.type === 'text') {
      options.transferData = transferData;
    }

    const id = options.formItemProps?.name || options.name || item.id;

    options.initialValue = transferData?.[id];
    options.ref = (ref: any) => (controlRefs.current[id] = ref);
    options.id = id;

    return (
      <Control {...options}>
        {item.children ? item.children.map(renderControl) : null}
      </Control>
    );
  }

  useEffect(() => {
    let historyLineKey = sessionStorage.getItem('myrequest_historyLineKey');
    if (historyLineKey) {
      const list = JSON.parse(historyLineKey) as any[];
      setHistoryLine(list.filter(item => item.action !== '100'));
    }
  }, []);

  return isRender ? (
    <div className={style.printStyle} id='printStyle' style={{ width: (formInfo?.printScale || 100) + '%', margin: '0 auto' }}>
      {structure.list ? structure.list.map(renderControl) : []}
      {Array.isArray(historyLine) && historyLine.length > 0 && <PrintTable title={window.$app.t('workflowHistory')} tableProps={tableProps} initialValue={historyLine} />}
    </div>
  ) : null;
};